from math import pi, sin, cos
import sys,os,subprocess
import traceback
import thread
import math

from direct.showbase.ShowBase import ShowBase
from direct.task import Task
from direct.actor.Actor import Actor
from direct.interval.IntervalGlobal import Sequence
from panda3d.core import Point3
from panda3d.core import Camera
from panda3d.core import WindowProperties
from panda3d.core import Loader 
from direct.gui.OnscreenText import OnscreenText


class Engine(ShowBase):
	instance = None
	def __init__(self):    	
		ShowBase.__init__(self)
		Engine.instance = self
		wp = WindowProperties()
		wp.setTitle("ProgrammedMe - Panda")
		wp.setOrigin(110, 110)
		base.win.requestProperties(wp)
		self.title = OnscreenText(text="Press Escape to exit",
                              style=1, fg=(1,1,0,1),
                              pos=(0.8,-0.95), scale = .07)

		

		# Disable the camera trackball controls.
		self.disableMouse()

		# Load the environment model.
		self.environ = self.loader.loadModel("models/environment")
		
		self.environ.reparentTo(self.render)
		# Apply scale and position transforms on the model.
		self.environ.setScale(0.25, 0.25, 0.25)
		self.environ.setPos(-8, 42, 0)

		# Add the spinCameraTask procedure to the task manager.
		#self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")

		# Load and transform the panda actor.
		self.panda = Actor("models/panda-model", {"walk": "models/panda-walk4"})
		self.panda.setScale(0.005, 0.005, 0.005)
		self.panda.reparentTo(self.render)
		# Loop its animation.
		#self.panda.loop("walk")
		self.panda.setPos(Point3(0, 10, 0))
		# Create the four lerp intervals needed for the panda to
		# walk back and forth.
		pandaPosInterval1 = self.panda.posInterval(13, Point3(0, -10, 0), startPos=Point3(0, 10, 0))
		pandaPosInterval2 = self.panda.posInterval(13,Point3(0, 10, 0),startPos=Point3(0, -10, 0))
		pandaHprInterval1 = self.panda.hprInterval(3,Point3(180, 0, 0),startHpr=Point3(0, 0, 0))
		pandaHprInterval2 = self.panda.hprInterval(3,Point3(0, 0, 0),startHpr=Point3(180, 0, 0))

		# Create and play the sequence that coordinates the intervals.
		self.pandaPace = Sequence(pandaPosInterval1, pandaHprInterval1, pandaPosInterval2, pandaHprInterval2, name="pandaPace")
		self.accept('escape',sys.exit)
		self.accept('r',self.readScript)
		self.isocam(None)	
		
		#create simple goal
		self.banana = loader.loadModel("models/banana.egg")
		self.banana.setPos(0,-10,0)
		self.banana.setScale(5)
		self.banana.reparentTo(render)
		#self.playmusic()

		self.info = OnscreenText(text="Panda Heading :" + `self.panda.getHpr()`,
                        style=1, fg=(1,1,0,1),
                        pos=(-0.7,-0.95), scale = .07)
		self.taskMgr.add(self.pandaInfo, "pandaInfo")
	
	def pandaInfo(self, task):
		self.info.setText("Panda Heading :" + `self.panda.getHpr()`)
		return Task.cont

	def isocam(self, task):
		cam = Camera("Isometric")
		base.cam.setPos(self.panda.getPos()+20) 
		base.cam.lookAt(self.panda)
		return Task.cont

	def readScript(self):
		try:
			execfile("script.py")
		except:
			s = traceback.format_exc()
			print(s)
	
	def evalscript(self, script):
		try:
			eval(script)
		except:
			return traceback.format_exc()

	def spinCameraTask(self, task):
		angleDegrees = task.time * 6.0
		angleRadians = angleDegrees * (pi / 180.0)
		self.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
		self.camera.setHpr(angleDegrees, 0, 0)
		self.camera.lookAt(self.panda)
		return Task.cont

	def monitorWalk(self, task):
		if self.walkSequence.isPlaying():
			pass
		else:
			self.taskMgr.remove("MonitorWalk")
			self.panda.stop()
		return Task.cont


'''============== PUBLISHED PANDA/ACTOR VOCABULLARIES
'''
def stop():
	self = Engine.instance
	self.taskMgr.remove("MonitorWalk")
	self.panda.stop()
	self.walkSequence.pause()

def walk(count = 1):
	self = Engine.instance

	startWalking = self.panda.loop("walk")
	startPos = self.panda.getPos()
	#determine where to move
	
	currentHpr = self.panda.getHpr()
	movement = Point3(0,0,0)
	
	print(currentHpr.getX())
	if currentHpr.getX() == 0 or currentHpr.getX() == -360:
		movement = Point3(0,-4 * count,0)
	elif currentHpr.getX() == 90 or currentHpr.getX() == -270:
		movement = Point3(4 * count,0,0)
	elif currentHpr.getX() == 180 or currentHpr.getX() == -180:
		movement = Point3(0, 4 * count,0)
	elif currentHpr.getX() == 270 or currentHpr.getX() == -90:
		movement = Point3(-4 * count,0,0)
	endPos = startPos + movement
	stopWalking = self.panda.stop()
	self.walkSequence = Sequence(self.panda.posInterval(4 * count, endPos, startPos))
	
	self.panda.loop("walk")
	self.walkSequence.start()
	self.taskMgr.add(self.monitorWalk, "MonitorWalk")

def left(degree = 90):
	self = Engine.instance

	#only the heading, getX() that we care about
	currentHpr = self.panda.getHpr()
	end = currentHpr + Point3(degree,0,0)
	end.setX(math.fmod(end.getX(), 360))

	pandaHprInterval1 = self.panda.hprInterval(2,end,currentHpr)
	self.walkSequence = Sequence(pandaHprInterval1)
	self.panda.loop("walk")
	self.walkSequence.start()
	self.taskMgr.add(self.monitorWalk, "MonitorWalk")

def right(degree = 90):
	left(degree * -1)

def follow():
	Engine.instance.taskMgr.add(Engine.instance.isocam, "isocamera")

def unfollow():
	Engine.instance.taskMgr.remove("isocamera")

def playmusic():
	self = Engine.instance
	self.music = base.loadMusic("sound/Purity.mp3")	
	self.music.play()

def stopmusic():
	self = Engine.instance
	self.music.stop()

def rollcam():
	self = Engine.instance
	if self.taskMgr.hasTaskNamed("SpinCameraTask"):
		self.taskMgr.remove("SpinCameraTask")
	else:
		self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")

def exit(self):		
	sys.exit